import pymysql

# 建立与MySQL数据库的连接
conn = pymysql.connect(
    host='localhost',
    port=3306,
    user='root',
    passwd='123456',
    database='demo01',
    charset='utf8mb4'
)

def con_my_sql(sql_code, params=None):
    """
    执行SQL语句的函数，支持参数化查询，增强安全性。

    :param sql_code: SQL语句模板，对于参数化查询部分用占位符表示（如 %s）
    :param params: 对应SQL语句模板中占位符的参数值，以元组或列表形式传入（可选参数，如果SQL语句不需要传入参数则可以不传）
    :return: 如果执行成功，返回游标对象；如果出现异常，返回包含异常类型和异常信息的元组
    """
    try:
        # 尝试重连数据库（如果连接断开的情况下）
        conn.ping(reconnect=True)

        # 指定游标类型为字典游标，这样查询结果可以以字典形式方便获取
        cursor = conn.cursor(pymysql.cursors.DictCursor)
        if params:
            # 如果有参数传入，使用参数化查询的方式执行SQL语句
            cursor.execute(sql_code, params)
        else:
            # 如果没有参数传入，直接执行SQL语句（适用于如不带参数的查询、更新等语句）
            cursor.execute(sql_code)
        # 如果是增删改操作，提交事务
        if sql_code.lower().startswith(('insert', 'update', 'delete')):
            conn.commit()

        return cursor
    except Exception as e:
        print(e)
        # 如果出现异常，回滚事务
        conn.rollback()
        return type(e), e
    finally:
        # 无论如何最后关闭连接
        conn.close()

# # 插入示例（使用参数化查询）
# username = "张三"
# pwd = "123456"
# # 这里使用参数化的方式构建SQL语句，表名和列名按规范使用反引号包围，占位符 %s 表示参数位置
# code = "INSERT INTO `login_user` (`username`, `password`) VALUES (%s, %s)"
# # 以元组形式传入对应占位符的参数值
# result = con_my_sql(code, (username, pwd))
# print(result)
#
# # 查询示例（使用参数化查询）
# username = "张三"
# # 同样使用参数化方式构建查询语句，占位符 %s 用于传入参数
# code = "select * from login_user where username = %s"
# # 传入参数值，以元组形式（即使只有一个参数也要用元组包裹）
# cursor_ans = con_my_sql(code, (username,))
# print(cursor_ans.fetchall())
# 插入示例（使用参数化查询）

# import SaltSM3
# # 测试存储SM3带盐值hash后的用户信息
# username = "张三"
# pwd = "123456"
# salt = SaltSM3.generate_salt()
# pwd_salt_hash = SaltSM3.hash_with_salt(pwd, salt)
# print(pwd_salt_hash)
# # 这里使用参数化的方式构建SQL语句，表名和列名按规范使用反引号包围，占位符 %s 表示参数位置
# code = "INSERT INTO `users` (`Username`, `PasswordHash`,`Salt`) VALUES (%s, %s, %s)"
# # 以元组形式传入对应占位符的参数值
# result = con_my_sql(code, (username, pwd_salt_hash,salt))
# print("result:",result)
#
# # 测试查询SM3带盐值hash后的用户信息并验证
# username = "张三"
# pwd = "123456"
# # 同样使用参数化方式构建查询语句，占位符 %s 用于传入参数
# code = "select * from users where Username = %s"
# # 传入参数值，以元组形式（即使只有一个参数也要用元组包裹）
# cursor_ans = con_my_sql(code, (username,))
# ans_dates = cursor_ans.fetchall()
# if len(ans_dates) > 0:
#     user_date = ans_dates[0]
#     PasswordHash = user_date['PasswordHash']
#     Salt = user_date['Salt']
#     password_salt_hash = SaltSM3.hash_with_salt(pwd,Salt)
#     if password_salt_hash == PasswordHash:
#         print("验证成功!")


